/***********************************************************************************
 * 文件名： rhc.c
 * 版本： 3
 * 说明：
 * 		RHC(Resistance heating controller 电阻加热控制器)，通过PWM控制发热电阻获得的电压值来
 *  控制发热，实现按照指定电压、功率、温度进行加热。
 *      目前只支持平均电压。
 *      目前只支持使用电池电压为ADC正极参考电压，采集内部固定参考电压的ADC采集方式。
 * 修改记录：
 * 	2021/04/21: 初版。 刘言。
 *  2021/05/07: 增加空载检测功能。刘言。
 *  2021/06/29: 增加正推ADC模式（模式1）支持。
***********************************************************************************/
#include "cpt-rhc.h"
#include "polsys.h"

#if _RHC_AD_MODE == 0
#if (_RHC_FULL_ADV > 255)
#define _RHC_VREFADV_LIMIT (u16)((u32)_RHC_VREF_VOLTAGE * _RHC_FULL_ADV / _RHC_VBAT_LIMIT)
#else
#define _RHC_VREFADV_LIMIT (u8)((u32)_RHC_VREF_VOLTAGE * _RHC_FULL_ADV / _RHC_VBAT_LIMIT)
#endif
#else
#if (_RHC_FULL_ADV > 255)
#define _RHC_VBATADV_LIMIT (u16)((u32)_RHC_VBAT_LIMIT * _RHC_LOW_RES * _RHC_FULL_ADV / (_RHC_HIGH_RES + _RHC_LOW_RES) / _RHC_ADC_VREF)
#else
#define _RHC_VBATADV_LIMIT (u8)((u32)_RHC_VBAT_LIMIT * _RHC_LOW_RES * _RHC_FULL_ADV / (_RHC_HIGH_RES + _RHC_LOW_RES) / _RHC_ADC_VREF)
#endif
#endif

u16 _RHC_mTarget; // 目标值
#if (_RHC_FULL_ADV > 255)
static u16 RHC_mOutAdv;
#if _RHC_AD_MODE == 0
static u16 RHC_mVrefAdv;
#else
static u16 RHC_mVbatAdv;
#endif
#else
static u8 RHC_mOutAdv;
#if _RHC_AD_MODE == 0
static u8 RHC_mVrefAdv;
#else
static u8 RHC_mVbatAdv;
#endif
#endif

static bit RHC_mNeedAdv = false; // 需要获取新的AD值
static rhc_ev_t RHC_mEvent = RHC_EV_NULL;
static bit RHC_mRun = false;
static u16 RHC_mHighVoltage; // 输出端口高电平电压,单位16mV

#if (_RHC_OC_ALLOW_CNT > 0)
static u8 RHC_mOCCnt; // 连续检测到过流的次数
#endif

#ifdef _RHC_USE_LOAD_CHECK
static rhc_load_status_t RHC_mLoadStatus;
static u8 RHC_mNoLoadCnt;
#ifdef _RHC_USE_LOADED_EVENT
static u8 RHC_mLoadedCnt;
#endif
#endif

// 声明引用事件通知函数（避免使用函数指针的妥协）
// 在你的应用代码中定义这个函数用于接收事件
void RHC_Event(rhc_ev_t e);

// 外部事件，这些函数由外部模块调用，用来通知本模块事件发生了

// PWM周期的 ON 跳变（开启输出）
void RHC_EvPWMOutON()
{
    if (RHC_mRun)
    {
#if _RHC_AD_MODE == 1
        _RHC_SetADCVrefVDD();
#endif
        _RHC_StartADC(_RHC_ADCH_OVAL); // 输出开启时立即采集端口电压AD值
    }
}

#if (_RHC_FULL_ADV > 255)
// AD转换完成
void RHC_EvADCCompleted(u16 adv)
#else
// AD转换完成
void RHC_EvADCCompleted(u8 adv)
#endif
{
    if (RHC_mRun && _RHC_OutIsON()) // 输出MOS是开启的
    {
        u8 ch = Adc_GetCH();
        if (ch == _RHC_ADCH_OVAL) // 是OVAL通道
        {
            if ((adv < _RHC_OC_ADVH)
#if (_RHC_OC_ADVL > 0)
                && (adv > _RHC_OC_ADVL)
#endif
                    ) // 过流检测
            {
#if (_RHC_OC_ALLOW_CNT > 0)
                RHC_mOCCnt++; // 连续检测到过流的次数+1
                if (RHC_mOCCnt >= _RHC_OC_ALLOW_CNT + 1)
#endif
                {
                    _RHC_Brake(); // 刹车，立即停止输出
                    RHC_mRun = false;
                    RHC_mEvent |= RHC_EV_SHORT_OUT;
                }
            }
#if (_RHC_OC_ALLOW_CNT > 0)
            else
            {
                RHC_mOCCnt = 0;
            }
#endif
            if (RHC_mNeedAdv) // 需要新的AD值
            {
                RHC_mOutAdv = adv;
#if (_RHC_KEEP_ADC)
#if _RHC_AD_MODE == 0
                ch = _RHC_ADCH_VREF; // 下一次转换VREF通道
#else
                ch = _RHC_ADCH_VBAT; // 下一次转换VBAT通道
#endif
#else
#if _RHC_AD_MODE == 0
                _RHC_StartADC(_RHC_ADCH_VREF);
#else
                _RHC_SetADCVrefVref();
                _RHC_StartADC(_RHC_ADCH_VBAT);
#endif
#endif
            }
            // else
            // {
            //     ch = _RHC_ADCH_OVAL;    // 下一次继续转换OVAL通道
            // }
        }
        else /*if(ch == _RHC_ADCH_VREF)*/
        {
#if _RHC_AD_MODE == 0
            RHC_mVrefAdv = adv;
#else
            RHC_mVbatAdv = adv;
#endif
            RHC_mNeedAdv = false;
#if (_RHC_KEEP_ADC)
            ch = _RHC_ADCH_OVAL; // 下一次转换OVAL通道
#endif
        }
#if (_RHC_KEEP_ADC)
#if _RHC_AD_MODE == 1
        if (ch == _RHC_ADCH_OVAL)
            _RHC_SetADCVrefVDD();
        else
            _RHC_SetADCVrefVref();
#endif
        _RHC_StartADC(ch); // MOS是开启的就不停的转换
#endif
    }
}

// 提供的接口

void RHC_Init()
{
    _RHC_InitPWM();
}

#ifdef _RHC_MULTI_MODE
void RHC_SetTarget(rhc_mode_t mode, u16 value)
{
#error " 当前版本不支持"
}
#endif

void RHC_Start()
{
#if (_RHC_OC_ALLOW_CNT > 0)
    RHC_mOCCnt = 0;
#endif
#ifdef _RHC_USE_LOAD_CHECK
    RHC_mLoadStatus = RHC_LOAD_NULL;
    RHC_mNoLoadCnt = 0;
    #ifdef _RHC_USE_LOADED_EVENT
    RHC_mLoadedCnt = 0;
    #endif
#endif
    RHC_mRun = true;
    RHC_mNeedAdv = true;
    _RHC_SetADCDiscardFlag();//第一次开启，开启一次adc滤波，避免第一次AD值偏差导致过流保护
    _RHC_SetPWM(255);
    _RHC_StartPWM();
    RHC_mEvent = RHC_EV_NULL;
}

void RHC_Stop()
{
    RHC_mRun = false;
    _RHC_Brake(); // 刹车，立即停止输出
}

// 间隔10~100ms执行一次
void RHC_Task()
{
    u8 new_pwm;
    u16 target_pwm;

    if (RHC_mRun)
    {
        if (RHC_mNeedAdv == false) // 说明AD值已经获取了
        {
#ifdef _RHC_USE_LOAD_CHECK
            if(RHC_mLoadStatus != RHC_NO_LOAD && RHC_mOutAdv >= _RHC_NO_LOAD_ADV)
            {
                RHC_mNoLoadCnt++;
                if(RHC_mNoLoadCnt == _RHC_NO_LOAD_ALLOW_CNT)
                {
                    RHC_mLoadStatus = RHC_NO_LOAD;
                    RHC_mEvent |= RHC_EV_NO_LOAD;
                }
            }
            else
            {
                RHC_mNoLoadCnt = 0;
            }
    #ifdef _RHC_USE_LOADED_EVENT
            if(RHC_mLoadStatus != RHC_LOADED && RHC_mOutAdv <= _RHC_LOADED_ADV)
            {
                RHC_mLoadedCnt++;
                if(RHC_mLoadedCnt == _RHC_LOADED_ALLOW_CNT)
                {
                    RHC_mLoadStatus = RHC_LOADED;
                    RHC_mEvent |= RHC_EV_LOADED;
                }
            }
            else
            {
                RHC_mLoadedCnt = 0;
            }
    #endif
#endif
#if _RHC_AD_MODE == 0
            if (RHC_mVrefAdv > _RHC_VREFADV_LIMIT)
#else
            if (RHC_mVbatAdv < _RHC_VBATADV_LIMIT)
#endif
            {
                // _RHC_Brake();   // 刹车，立即停止输出
                // RHC_mRun = false;
                RHC_Stop();
                RHC_mEvent |= RHC_EV_NO_BATTERY; // 优先级更高的事件覆盖前面的事件
            }
#if _RHC_AD_MODE == 0
            RHC_mHighVoltage = ((u16)((u16)(_RHC_VREF_VOLTAGE / 16) * (u8)RHC_mOutAdv) / (u8)RHC_mVrefAdv); //计算电压,单位16mV
#else
            // RHC_mHighVoltage = (u16)((u32)(RHC_mOutAdv * RHC_mVbatAdv*((u32)_RHC_ADC_VREF * (_RHC_HIGH_RES + _RHC_LOW_RES))) / ((u32)_RHC_FULL_ADV * _RHC_FULL_ADV * _RHC_LOW_RES * 16));
            RHC_mHighVoltage = (u16)RHC_mOutAdv * RHC_mVbatAdv / (u16)(((u32)_RHC_FULL_ADV * _RHC_FULL_ADV * _RHC_LOW_RES * 16) / ((u32)_RHC_ADC_VREF * (_RHC_HIGH_RES + _RHC_LOW_RES)));
            // RHC_mOutAdv * RHC_mVrefAdv * _RHC_ADC_VREF * (_RHC_HIGH_RES + _RHC_LOW_RES) / _RHC_LOW_RES / _RHC_FULL_ADV / _RHC_FULL_ADV / 16;
#endif
            target_pwm = (_RHC_mTarget >> 4) * 255 / RHC_mHighVoltage;
            // if (new_pwm < 100)//0x164=>0x64=>100=>2865mv@目标值4V；目标值4V，电池电压在2.865V-4.0V之间输出255
            //     new_pwm = 255;
            if(target_pwm > 255)new_pwm = 255;
            else new_pwm = target_pwm;
            _RHC_SetPWM(new_pwm);
            RHC_mNeedAdv = true;
        }
    }
    if (RHC_mEvent != RHC_EV_NULL)
    {
        RHC_Event(RHC_mEvent);
        RHC_mEvent = RHC_EV_NULL;
    }
}
